//给定一个按照升序排列的整数数组 nums，和一个目标值 target。找出给定目标值在数组中的开始位置和结束位置。 
//
// 如果数组中不存在目标值 target，返回 [-1, -1]。 
//
// 进阶： 
//
// 
// 你可以设计并实现时间复杂度为 O(log n) 的算法解决此问题吗？ 
// 
//
// 
//
// 示例 1： 
//
// 
//输入：nums = [5,7,7,8,8,10], target = 8
//输出：[3,4] 
//
// 示例 2： 
//
// 
//输入：nums = [5,7,7,8,8,10], target = 6
//输出：[-1,-1] 
//
// 示例 3： 
//
// 
//输入：nums = [], target = 0
//输出：[-1,-1] 
//
// 
//
// 提示： 
//
// 
// 0 <= nums.length <= 105 
// -109 <= nums[i] <= 109 
// nums 是一个非递减数组 
// -109 <= target <= 109 
// 
// Related Topics 数组 二分查找 
// 👍 1302 👎 0

package com.cute.leetcode.editor.cn;
public class FindFirstAndLastPositionOfElementInSortedArray {
    public static void main(String[] args) {
        int[] nums = {5,7,7,8,8,10};
        new FindFirstAndLastPositionOfElementInSortedArray().new Solution().searchRange(nums, 8);
    }
    //leetcode submit region begin(Prohibit modification and deletion)
    class Solution {
        /**
         * 查找数组中target起始坐标和结束坐标
         * 没找到的话给[-1,-1]
         * 1.暴力搜索，时间复杂度n
         * 2.二分法，时间复杂度为logn
         *      先找出来这个数再遍历？
         *      找这个数不难，但是如何找到所有的这个数呢？如果扩散查找的话空间复杂度还是N
         *      寻找两个位置时也需要使用二分查找，一个是寻找左边，一个是寻找右边
         *      注意两个方法中区间更新以及mid取值有所不同，寻找左界时mid向下取整
         *      寻找右边界时为了防止死循环，mid设置成为了向上取整
         *      注意查找过程中区间的更新，是比较关键的
         */
        public int[] searchRange(int[] nums, int target) {
            if (nums.length == 0) return new int[]{-1,-1};
            int firstPosition = findFirstPosition(nums, target);
            if (firstPosition == -1) return new int[]{-1,-1};
            int lastPosition = findLastPosition(nums, target);
            return new int[]{firstPosition,lastPosition};
        }

        public int findFirstPosition(int[] nums, int target){
            int left = 0;
            int right = nums.length-1;
            int mid;
            while (left < right){
                //因为迭代条件时left<right，这里向下取整保证mid接近于left，使得结束迭代时left能够指向目标值
                mid = left + (right- left)/2;
                if (nums[mid]>=target) right = mid;
                else left = mid+1;
            }
            if (nums[left] == target) return left;
            else return -1;
        }

        public int findLastPosition(int[] nums, int target){
            int left = 0;
            int right = nums.length-1;
            int mid;
            while (left < right){
                //向上取整，这样mid会更接近于与right重合，否则根据left=mid的话会死循环，left和mid会一直重合
                mid = left + (right - left +1)/2;
                if (nums[mid]>target) right = mid-1;
                else left = mid;
            }
            return left;//能到查最后一次出现的时候说明target一定时存在的
        }
    }
//leetcode submit region end(Prohibit modification and deletion)

}